package com.ecreditpal.audio.netty.handler;

import com.google.protobuf.MessageLite;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * @author lifeng
 * @version 1.0 on 2018/7/12.
 */
@Slf4j
public class HeartBeatRespHandler extends ChannelInboundHandlerAdapter {
    private int lossConnectCount = 0;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("start heartBeat schedule,address:{}",ctx.channel().remoteAddress());
        ctx.executor().scheduleAtFixedRate(new HeartBeatTask(ctx), 0, 15000, TimeUnit.MILLISECONDS);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        log.info("no msg for 20 second");
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                lossConnectCount++;
                if (lossConnectCount > 5) {
                    log.info("close inactive channel");
                    ctx.channel().close();
                }
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        log.info("get data from remote:{}",ctx.channel().remoteAddress());
        lossConnectCount = 0;
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("error occurred while dealing with heart beat,address:{}",ctx.channel().remoteAddress(),cause);
        ctx.close();
    }


    private class HeartBeatTask implements Runnable {
        private final ChannelHandlerContext ctx;

        public HeartBeatTask(ChannelHandlerContext ctx) {
            this.ctx = ctx;
        }

        @Override
        public void run() {
            log.info("send heart beat to remote:{}",ctx.channel().remoteAddress());
            this.ctx.writeAndFlush(new Object());
        }
    }
}
